package tgc.edu.exam.web.controller;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.UUID;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import tgc.edu.exam.custom.CommonController;
import tgc.edu.exam.custom.DataGridParam;
import tgc.edu.exam.custom.DataGridUtils;
import tgc.edu.exam.custom.TablePageable;
import tgc.edu.exam.custom.dict.entity.SystemData;
import tgc.edu.exam.custom.dict.entity.SystemDictionaries;
import tgc.edu.exam.custom.dict.service.SystemDataService;
import tgc.edu.exam.custom.dict.service.SystemDicationariesService;
import tgc.edu.exam.entity.AskForleave;
import tgc.edu.exam.entity.Student;
import tgc.edu.exam.entity.SysRole;
import tgc.edu.exam.entity.SysUser;
import tgc.edu.exam.entity.TbClass;
import tgc.edu.exam.entity.Teacher;
import tgc.edu.exam.security.UserUtils;
import tgc.edu.exam.service.StudentService;
import tgc.edu.exam.service.SysRoleService;
import tgc.edu.exam.service.TbClassService;
import tgc.edu.exam.web.form.StudentForm;

@Controller
@RequestMapping(value = "/student")
public class StuController extends CommonController<Student, UUID, StudentForm> {
	@Autowired
	private TbClassService csService;
	@Autowired
	private StudentService service;
	@Autowired
	private SysRoleService roleService;
	@Autowired
	private SystemDicationariesService dictService;
	@Autowired
	private SystemDataService dataService;
	@Autowired
	private UserUtils userUtils;

	@RequestMapping(value = "/audit")
	public void audit(ModelMap map) {
		SysUser sysUser = userUtils.getUser();
		if (sysUser != null) {
			Specification<TbClass> spec = buildSpec3(sysUser);
			List<TbClass> bjs = csService.findAll(spec);
			map.put("bjs", bjs);
		} else {
			Specification<TbClass> spec = buildSpec3(null);
			List<TbClass> bjs = csService.findAll(spec);
			map.put("bjs", bjs);
		}
	}

	@RequestMapping(value = "/instant")
	@ResponseBody
	public Object instant() {
		String msg = "";
		try {
			SysUser user = userUtils.getUser();
			Specification<Student> spec = buildSpec1(user,null);
			List<Student> students = service.findAll(spec);
			SysRole role = roleService.findbyCode("ROLE_STUDENT");
			if (students.size() != 0) {
				for (Student student : students) {
					student.setType("已通过");
					student.setIsUsed(true);
					student.getRoles().add(role);
					service.save(student);
				}
				msg = "操作完成！";
			} else {
				msg = "没有要审核的数据哟！";
			}
		} catch (Exception e) {
			msg = "数据异常！请联系管理员";
		}
		return msg;
	}

	@RequestMapping(value = "/agree")
	@ResponseBody
	public Object agree(String id) {
		try {
			Student student = service.findById(UUID.fromString(id));
			if (student != null) {
				SysRole role = roleService.findbyCode("ROLE_STUDENT");
				student.setType("已通过");
				student.setIsUsed(true);
				student.getRoles().add(role);
				service.save(student);
				return "操作完成！";
			} else {
				return "数据异常！请联系管理员";
			}
		} catch (Exception e) {
			return "数据异常！请联系管理员";
		}
	}

	@RequestMapping(value = "/repulse")
	@ResponseBody
	public Object refuse(String id, String yuanyi) {
		String msg = "数据出错！请联系管理员";
		try {
			Student student = service.findById(UUID.fromString(id));
			if (student != null) {
				student.setType("已拒绝");
				student.setYuanying(yuanyi);
				student.setTbClass(null);
				service.save(student);
				msg = "操作成功！";
			}
		} catch (Exception e) {
			msg = "数据异常！请联系管理员";
		}
		return msg;
	}
	
	/**
	 * 班级显示班级成员
	 * @param param
	 * @param tbClassid
	 * @return
	 */
	@RequestMapping(value="/page2")
	@ResponseBody
	public Object page2(DataGridParam param, String tbClassid) {
		Sort sort=Sort.by("createDate");
		Pageable pageable = param.getPageable(sort);
		Specification<Student> spec = buildSpec2(tbClassid);
		Page<Student> page = service.findAll(spec, pageable);
		return DataGridUtils.buildResult(page);
	}
	
	private Specification<Student> buildSpec2(String tbClassid) {
		Specification<Student> spec = new Specification<Student>() {

			@Override
			public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules = new HashSet<>();
				if(StringUtils.hasText(tbClassid)) {
					rules.add(cb.equal(root.get("tbClass").get("id"), UUID.fromString(tbClassid)));
				}
				return cb.and(rules.toArray(new Predicate[rules.size()]));
			}
		};
		return spec;
	}

	@RequestMapping(value = "/page1")
	@ResponseBody
	public Object page1(TablePageable pageParam , String bjuuid) {
		PageRequest pageable = pageParam.bulidPageRequest();
		SysUser user = userUtils.getUser();
		Specification<Student> spec = buildSpec1(user,bjuuid);
		Page<Student> page = service.findAll(spec, pageable);
		return DataGridUtils.buildResult(page);
	}

	private Specification<Student> buildSpec1(SysUser user, String bjuuid) {
		Specification<Student> spec = new Specification<Student>() {

			@Override
			public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules = new HashSet<>();
				if (user != null) {
					rules.add(cb.equal(root.get("tbClass").get("teacherId").get("id"), user.getId()));
				}
				if(StringUtils.hasText(bjuuid)) {
					rules.add(cb.equal(root.get("tbClass").get("id"), UUID.fromString(bjuuid)));
				}
				rules.add(cb.equal(root.get("type"), "待审核"));
				return cb.and(rules.toArray(new Predicate[rules.size()]));
			}
		};
		return spec;
	}

	@Override
	public void edit(StudentForm form, ModelMap map) throws InstantiationException, IllegalAccessException {
		List<TbClass> bjs = csService.findAll();
		map.put("bjs", bjs);
		SystemDictionaries systemDictionaries = dictService.findByCode("nation");
		List<SystemData> data = dataService.findBySystemDictionaries(systemDictionaries);
		map.put("data", data);
		SystemDictionaries systemDictionaries1 = dictService.findByCode("political_outlook");
		List<SystemData> data1 = dataService.findBySystemDictionaries(systemDictionaries1);
		map.put("data1", data1);
		SystemDictionaries systemDictionaries2 = dictService.findByCode("education");
		List<SystemData> data2 = dataService.findBySystemDictionaries(systemDictionaries2);
		map.put("data2", data2);
		SystemDictionaries systemDictionaries3 = dictService.findByCode("Class_duties");
		List<SystemData> data3 = dataService.findBySystemDictionaries(systemDictionaries3);
		map.put("data3", data3);
		super.edit(form, map);
	}

	@Override
	public Object save(StudentForm form) {
		UUID id = form.getTbClass().getId();
		if (id == null) {
			form.setTbClass(null);
		}
		return super.save(form);
	}

	@RequestMapping(value = "select")
	@ResponseBody
	public Object select(String id) {
		TbClass tbClass = csService.findById(UUID.fromString(id));
		List<Student> list = service.findByTbClassId(tbClass.getId());
		return list;
	}

	@Override
	public void manage(ModelMap map) {
		boolean ishas = false;
		SysUser sysUser = userUtils.getUser();
		if (sysUser != null) {
			List<SysRole> roles = sysUser.getRoles();
			for (SysRole sysRole : roles) {
				List<SysRole> children = sysRole.getChildren();
				for (SysRole sysRole2 : children) {
					String code = "ROLE_CHKWQXY";
					String rolecode = sysRole2.getCode();
					if (code.equals(rolecode)) {
						ishas = true;
					}
				}
			}
			if (ishas) {
				Specification<TbClass> spec = buildSpec3(null);
				List<TbClass> bjs = csService.findAll(spec);
				List<Student> list = service.findByTbClassId(bjs.get(0).getId());
				map.put("bjs", bjs);
				map.put("stu", list);
			} else {
				Specification<TbClass> spec = buildSpec3(sysUser);
				List<TbClass> bjs = csService.findAll(spec);
				List<Student> list = service.findByTbClassId(bjs.get(0).getId());
				map.put("bjs", bjs);
				map.put("stu", list);
			}
		} else {
			ishas = true;
			Specification<TbClass> spec = buildSpec3(null);
			List<TbClass> bjs = csService.findAll(spec);
			List<Student> list = service.findByTbClassId(bjs.get(0).getId());
			map.put("bjs", bjs);
			map.put("stu", list);
		}
		map.put("ishas", ishas);

		super.manage(map);
	}

	private Specification<TbClass> buildSpec3(SysUser sysUser) {
		Specification<TbClass> spec = new Specification<TbClass>() {
			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<TbClass> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules = new HashSet<>();
				if (sysUser != null) {
					rules.add(cb.equal(root.get("teacherId").get("id"), sysUser.getId()));
				}
				rules.add(cb.notEqual(root.get("classStatus").get("state"), "结业"));
				return cb.and(rules.toArray(new Predicate[rules.size()]));
			}
		};
		return spec;
	}

	@RequestMapping(value = "/banjiselect")
	@ResponseBody
	public Object banjiselect(boolean isstart) {
		if (isstart) {
			List<TbClass> bjs = csService.findAll();
			List<TbClass> list = new ArrayList<>();
			for (TbClass tbClass : bjs) {
				String state = tbClass.getClassStatus().getState();
				if ("结业".equals(state)) {
					tbClass.setName(tbClass.getName() + "(结业班级)");
					list.add(tbClass);
				}
			}
			return list;
		} else {
			Specification<TbClass> spec = buildSpec3(null);
			List<TbClass> bjs = csService.findAll(spec);
			return bjs;
		}
	}

	@Override
	public Specification<Student> buildSpec(StudentForm form) {
		Specification<Student> spec = new Specification<Student>() {

			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules = new HashSet<>();
				String name = form.getName();
				if (StringUtils.hasText(name)) {
					rules.add(cb.like(root.get("name"), "%" + name + "%"));
				}
				String username = form.getUsername();
				if (StringUtils.hasText(username)) {
					rules.add(cb.like(root.get("username"), "%" + username + "%"));
				}
				String sex = form.getSex();
				if (StringUtils.hasText(sex)) {
					rules.add(cb.equal(root.get("sex"), sex));
				}
				String address = form.getAddress();
				if (StringUtils.hasText(address)) {
					rules.add(cb.like(root.get("address"), "%" + address + "%"));
				}
				String phone = form.getPhone();
				if (StringUtils.hasText(phone)) {
					rules.add(cb.like(root.get("phone"), "%" + phone + "%"));
				}
				String workUnit = form.getWorkUnit();
				if (StringUtils.hasText(workUnit)) {
					rules.add(cb.like(root.get("workUnit"), "%" + workUnit + "%"));
				}
				String bjuuid = form.getBjuuid();
				if (StringUtils.hasText(bjuuid)) {
					rules.add(cb.equal(root.get("tbClass").get("id"), UUID.fromString(bjuuid)));
				}
				String suuid = form.getSuuid();
				if (StringUtils.hasText(suuid)) {
					rules.add(cb.equal(root.get("id"), UUID.fromString(suuid)));
				}
				rules.add(cb.equal(root.get("isUsed"), true));
				return cb.and(rules.toArray(new Predicate[rules.size()]));
			}
		};
		return spec;

	}

}
